/** Clase para mostrar la informacion sobre una interfaz selecionada. **/

package clientegestionred;

import common.Consulta;
import common.Cons;
import common.SesionSNMP;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.snmp4j.smi.*;


public class InfoInterfaz implements Cons {

    private SesionSNMP ReadSesion; //sesion de lectura

    private Consulta consulta; //para hacer consultas
    
    private Variable [] response=new Variable []{}; //objeto que almacena las
                                                    //respuestas de consulta
    // OIDs como arrays
    private static final OID [] ifNumber = new OID []{if_Number};
    private static final OID [] sysUpTime = new OID[]{SYS_UPTIME};
    private static final OID [] ifLastChange = new OID[]{if_Last_Change};


    /* Constructor */
    public InfoInterfaz(SesionSNMP sesion) {
        ReadSesion = sesion;
        consulta = new Consulta(ReadSesion);
    }


    /* Metodo principal de la clase, que muestra informacion general sobre la
     interfaz selecionada */
    public int start() throws IOException {

        System.out.println("\nA continuacion se muestran las interfaces que" +
                " que posee el equipo:");
        System.out.flush();
        int interf=this.selectInterface(consulta);
        if (interf == -1){
            System.err.println("\n\tValor no valido.");
            return -1;
        }

        // Muestra de informacion general de la interfaz
        infoGeneral(interf, consulta);

        // Muestra de informacion sobre errores en la interfaz
        errorInterfaz(interf, consulta);

        // Calculo de los segundos que lleva la interfaz funcionando
        float secondsInterf=calculaSegInter(consulta);

        // Calculo del consumo de entrada y salida
        float inConsumo=calculaConsumo(secondsInterf,interf,true,consulta);
        float outConsumo=calculaConsumo(secondsInterf,interf,false,consulta);

        // Calculo de datos totales y porcentajes
        int inOctets=calculaOctetos(interf, true, consulta);
        int outOctets=calculaOctetos(interf, false, consulta);
        float totalOctets=0;
        totalOctets=inOctets+outOctets;
        float totalConsumo=0;
        totalConsumo=inConsumo+outConsumo;
        float inPorcen=0;
        float outPorcen=0;
        if(totalConsumo!=0)
        {
            inPorcen=(inConsumo/totalConsumo)*100;
            outPorcen=(outConsumo/totalConsumo)*100;
        }

        // Muestra por pantalla el consumo total
        infoTrafico(totalOctets,false,false,false);
        // Muestra por pantalla el consumo medio
        infoTrafico(totalConsumo, true,false,false);
        // Muestra el porcentaje de trafico de entrada
        infoTrafico(inPorcen,false,true,true);
        // Muestra el porcentaje de trafico de salida
        infoTrafico(outPorcen,false,true,false);

        return 0;
    }//start()

    /* Metodo que muestra las interfaces disponibles en tu equipo y devuelve la
     seleccionada por el usuario */
    private int selectInterface(Consulta consulta) throws IOException
    {
        int interf = 0;
        // Mostrar interfaces del equipo
        response=consulta.get(ifNumber);
        int totalInterfaces = response[0].toInt();
        OID [] ifDescr;
        for(int i=1;i<=totalInterfaces;i++)
        {
            ifDescr= new OID []{new OID("1.3.6.1.2.1.2.2.1.2."+i)};
            response=consulta.get(ifDescr);
            System.out.println(" " + i+"- "+response[0].toString());
        }
        System.out.print("Elija la interfaz de la que desee ver su informacion" +
                    " general y rendimiento: ");
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        String bReaderString= bReader.readLine();
        try{
            interf=Integer.parseInt(bReaderString.trim());
        }catch(java.lang.NumberFormatException ex){}

        // Comprobar que lo introducido es valido
        if (interf <= 0 || interf > totalInterfaces){ return -1; }

        return interf;
    }//selectInterface

    /* Metodo que muestra la informacion general de la interfaz */
    private void infoGeneral (int interf, Consulta consulta) throws IOException
    {
        OID[] oids = new OID[]{new OID("1.3.6.1.2.1.2.2.1.2."+interf),
        new OID("1.3.6.1.2.1.2.2.1.3."+interf),
        new OID("1.3.6.1.2.1.2.2.1.4."+interf),
        new OID("1.3.6.1.2.1.2.2.1.6."+interf),
        new OID("1.3.6.1.2.1.2.2.1.16."+interf)};
        response = consulta.get(oids);
        String tipo = response[1].toString();
        String bytes = response[4].toString();
        System.out.println("\nDescripcion");
        System.out.println("\tNombre: " + response[0].toString());
        System.out.println("\tTipo: " + traduceTipo(tipo));
        System.out.println("\tMTU: " + response[2].toString());
        System.out.println("\tMAC: " + response[3].toString());
        System.out.println("\tBytes enviados hasta el momento: " + miraByte(bytes));
        System.out.flush();
    } //infoGeneral

    /* Metodo que traduce el entero del tipo de interfaz a su descripcion
     correspondiente */
    private String traduceTipo(String tipo){
        int n = Integer.parseInt(tipo);
        String resultado;
        switch(n)
        {
            case 6:
                resultado = "ethernet-csmacd";
                return resultado;

                case 18:
                resultado = "dsl";
                return resultado;

                case 23:
                resultado = "ppp";
                return resultado;

                case 20:
                resultado = "BasicISDN";
                return resultado;

            case 24:
                resultado = "softwareLoopback";
                return resultado;
            default:
                resultado ="Sin tipo especificado";
                return resultado;

        }
    } //traduceTipo

    /* Metodo que muestra los bytes en la unidad correcta */
    private String miraByte(String bytes){
        int n = Integer.parseInt(bytes);
        if(n < 1024)
        {
            String resultado = n+ " bytes";
            return resultado;
        }
        else{
            if(n< 1048576){
                double h= (double)n/1024;
                h = redondear(h);
                String resultado = h+ " Kbytes";
                return resultado;
           }
           double h = (double)n/1048576;
           h = redondear(h);
           String resultado = h+ " Mbytes";
           return resultado;
        }

    }//miraByte

    /* Metodo que muestra los errores de la interfaz consultada */
    private void errorInterfaz(int interf, Consulta consulta) throws IOException
    {
        System.out.println("\nErrores producidos en el Interfaz");
        System.out.flush();

        // Errores a la entrada
        OID[] oids = new OID[]{new OID("1.3.6.1.2.1.2.2.1.13."+interf),
        new OID("1.3.6.1.2.1.2.2.1.14."+interf),  //paquetes con errores
        new OID("1.3.6.1.2.1.2.2.1.15."+interf),  //paquetes descartados por
                                                  //desconocer el protocolo
        // Errores a la salida
        new OID("1.3.6.1.2.1.2.2.1.19."+interf),   //descartados a la salida
        new OID("1.3.6.1.2.1.2.2.1.20."+interf)};  //con errores a la salida

        // Enviar la consulta
        response=consulta.get(oids);

        // Imprimir la informaicon
        System.out.println("\tPaquetes descartados (IN): "+response[0]);
        System.out.println("\tPaquetes erroneos (IN): "+response[1]);
        System.out.println("\tPaquetes descartados por desconocer el protocolo "
                + "(IN): "+response[2]+"\n");
        System.out.println("\tPaquetes descartados (OUT): "+response[3]);
        System.out.println("\tPaquetes con errores (OUT): "+response[4]);
        System.out.flush();

    }//errorInterfaz

    /* Metodo que calcula los segundos que lleva funcionando la interfaz
     selecionada */
    private float calculaSegInter(Consulta consulta) throws IOException
    {
        // Calculo de los segundos que lleva el equipo encendido
        response=consulta.get(sysUpTime);
        int hundredths=response[0].toInt();
        float secondsSystem=hundredths/100;

        // Calculo de los segundos que lleva la interfaz funcionando
        response=consulta.get(ifLastChange);
        int lastChangeHundredths=response[0].toInt();
        float secondsLastChange=0;
        secondsLastChange=lastChangeHundredths/100;
        float secondsInterf=0;
        secondsInterf=secondsSystem-secondsLastChange;
        return secondsInterf;
    }//calculaSegInter

    /* Metodo que calcula el numero de octetos de entrada y de salida
     registrados en la interfaz selecionada */
    private int calculaOctetos(int interfaz,boolean entrada, Consulta consulta)
            throws IOException
    {
        OID [] ifOctets;
        if(entrada) ifOctets = new OID []{new OID("1.3.6.1.2.1.2.2.1.10."+
                interfaz)};
        else ifOctets = new OID []{new OID("1.3.6.1.2.1.2.2.1.16."+interfaz)};
        response=consulta.get(ifOctets);
        int octets=0;
        octets=response[0].toInt();
        return octets;
    }//calculaOctetos

    /* Metodo que calcula el consumo de entrada y salida registrado en
     la interfaz selecionada */
    private float calculaConsumo(float segundos, int interfaz,boolean entrada,
            Consulta consulta) throws IOException
    {
        int octets;
        if(entrada) octets = calculaOctetos(interfaz, true, consulta);
        else  octets = calculaOctetos(interfaz, false, consulta);
        float consumo=0;
        consumo=octets/segundos;
        return consumo;
    }//calculaConsumo

    /* Metodo que imprime en las unidades adecuadas la informacion del trafico
     total consumido, del trafico medio y del tipo de trafico */
    private void infoTrafico (float info,boolean consumo,boolean trafico,boolean in)
    {
        if(!trafico)
        {
            if (!consumo) System.out.println("\nConsumo total");
            else System.out.println("\nConsumo medio");

            if(info>1024)
            {
               if(info>1048576)
               {
                  if(!consumo)
                      System.out.println("\tHasta este momento se han consumido "+
                      redondear((double)info/1048576)+" Mbytes.");
                  else
                      System.out.println("\tEl tráfico medio es de "+redondear(
                              (double)(info/1048576))+" Mbps.");
               }
               else
               {
                  if(!consumo)
                      System.out.println("\tHasta este momento se han consumido "+
                      info/1024 + " Kbytes.");
                  else
                      System.out.println("\tEl tráfico medio es de "+(redondear(
                              (double)(info/1024)))+" Kbps.");
               }
            }
            else if (!consumo)
                    System.out.println("\tHasta este momento se han consumido "+
                    info+" bytes.");
                 else
                    System.out.println("\tEl tráfico medio es de "+(redondear(
                            (double)(info)))+" bps.");
        }
        else
        {
           if(in)
           {
                System.out.println("\nTipo de trafico");
              System.out.println("\tEl tráfico de entrada representa un " +
                      redondear((double)info)+"%" +
              " del trafico total.");
           }
           else
              System.out.println("\tEl tráfico de salida representa un " +
                      redondear((double)info)+"%" +
              " del trafico total.\n");
        }

    }//printInfo

    /* Redondear 2 decimales */
    private double redondear(double n){
        return Math.rint(n *100)/100;
    }

} //class